#ifndef LFDNODE_H
#define LFDNODE_H

#include "Export.h"
#include <osg/Group>
#include <osg/ProxyNode>
#include <osgEarth/Bounds>
#include <osgGA/GUIEventHandler>
#include <osgDB/Options>
#include <amk3/BaseScene.h>

class LFDOption;
class LFDEventHandler;

static const std::string LFD_VERSION = "LFD_VERSION";

class LFDNode : public osg::Group
{
public:
    LFDNode();


    // Node interface
public:
    void traverse(osg::NodeVisitor &);

    /** Set the optional database osgDB::Options object to use when loading children.*/
    void setDatabaseOptions(LFDOption* options) { _lfdOption = options; }

    /** Get the optional database osgDB::Options object used when loading children.*/
    LFDOption* getDatabaseOptions() { return _lfdOption.get(); }

    void update(int v);

    bool addChild(osg::Node *child);


    inline int getNodeVersion(){return _nodeVersion;}

protected:
    typedef std::pair< std::string, osg::ref_ptr<osg::Referenced> >  FileNameDatabaseRequestPair;
    //typedef std::vector<FileNameDatabaseRequestPair>                 FileNameDatabaseRequestList;
    FileNameDatabaseRequestPair     _request;
    osg::ref_ptr<LFDOption>        _lfdOption;
    int _nodeVersion;
};



struct LFDLevel{
    double min;
    double max;
    bool isPaged;
};

class CB_API LFDSource : public BaseScene
{
public:
    LFDSource();
    virtual ~LFDSource();

    virtual void open();
	virtual void close();
	virtual void update();

    virtual bool parseNode(const char* data,int length,osg::Group* parent,const LFDOption* option);
    typedef std::vector<LFDLevel> DATALEVELS;

    virtual std::string buildUrl(int lv,osgEarth::Bounds& bs);

    inline std::string getBaseUrl(){return _baseUrl;}
    inline void setBaseUrl(std::string url){_baseUrl = url;}
    inline osgEarth::Bounds getBounds(){return _bounds;}
    inline void setBounds(osgEarth::Bounds b){_bounds = b;}
    void addLevel(float min,float max,bool paged);
    inline DATALEVELS& levels(){return _levels;}
    inline bool getVisible(){return _rootNode.valid() && _visible;}
    void setVisible(bool b);
protected:
    std::string _baseUrl;
    osgEarth::Bounds _bounds;
    DATALEVELS _levels;
    osg::ref_ptr<LFDEventHandler> _eventHandler;
    osg::ref_ptr<osg::Group> _rootNode;
    std::vector<osg::ref_ptr<LFDNode>> _lfdNodes;
    bool _visible;
};

class LFDEventHandler : public osgGA::GUIEventHandler
{
    // EventHandler interface
public:
    bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
    osg::ref_ptr<LFDSource> _source;
};

class LFDOption :public osgDB::Options{

public:
    LFDOption();
    LFDOption(const LFDOption& o,const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
    META_Object(LFD, LFDOption)
public:
    int level;
    int version;
    std::string url;
    osg::ref_ptr<LFDSource> source;
    osgEarth::Bounds bounds;
};


#endif // LFDNODE_H
